home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / dev / c / cweb31p9d.lha / CWeb / examples / matrix.wpp < prev    next >
Text File  |  1994-04-02  |  18KB  |  484 lines

  1. %
  2. % CWEB $VER: matrix.wpp 1.2 (3.1.1994)
  3. %
  4. % BESCHREIBUNG: Dieses CWEB Programm soll als Beispiel für einige
  5. %               Erweiterungen dienen, die erst mit der neuen Version 3
  6. %               des CWEB-Systems verfügbar sind.  Es liest die Datei
  7. %               `Matrix.input', die in vier Zeilen jeweils vier Einträge
  8. %               der Form `(Realteil,Imaginärteil)' enthalten, und berechnet
  9. %               zu der so definierten komplexen Matrix die Inverse.  Ist
  10. %               die Eingabedatei nicht vorhanden, werden die entsprechenden
  11. %               Werte vom Benutzer angefordert.  Als Besonderheiten für
  12. %               CWEB-Interessierte möchte ich zwei Punkte anführen.  Zuerst
  13. %               und vor allem ist es ein deutsches Programm, sowohl die Ein-
  14. %               als auch die Ausgabe ist für diese Sprache gedacht.  Für die
  15. %               TeXnische Weiterverarbeitung wird also `gcwebmac.tex'
  16. %               benötigt, da dort die entsprechende Anpassung bezüglich
  17. %               der Umlaute und Anführungszeichen enthalten ist.
  18. %               Zweitens ist es ein C++ Programm und muß deshalb mit
  19. %               CWEB 3.0 verarbeitet werden; ältere Versionen ohne
  20. %               die Change-Datei von Hans-Hermann Bode werden ihre
  21. %               Schwierigkeiten haben.  Außerdem muß zur Übersetzung ein
  22. %               C++-Compiler benutzt werden.
  23. %
  24. % ERSTELLUNGSDATUM: 21.11.1993 (V1.0)
  25. %
  26. % AUTOR: Andreas Scherer
  27. %         Abt-Wolf-Straße 17
  28. %         96215 Lichtenfels
  29. %         Germany
  30. %
  31. % ÄNDERUNGEN: 26.11.1993: <stdlib.h> muß *nach* <complex.h> eingebunden
  32. %                         werden, sonst meckert SAS/C++ 6.50 (V1.1)
  33. %             03.01.1994: Version als konstanter Zeiger (V1.2)
  34. %
  35. % URHEBERRECHT: (c) 1993 Andreas Scherer
  36. %
  37. % Die Anfertigung und Verteilung von unveränderten Kopien der
  38. % elektronischen Form dieses Dokumentes ist erlaubt, sofern der
  39. % Urheberrechtshinweis und dieser Berechtigungshinweis bei allen
  40. % Kopien erhalten bleibt.
  41. %
  42. % Die Anfertigung und Verteilung von veränderten Versionen dieses
  43. % Dokumentes ist erlaubt unter den Bedingungen für unveränderte Kopien,
  44. % sofern das gesamte hiervon abgeleitete Werk unter den Bedingungen eines
  45. % mit diesem vergleichbaren Berechtigungshinweises verteilt wird.
  46.  
  47. % Spezielle Fonts für Teile der Dokumentation.
  48. %
  49. \font\ams=msbm10
  50.  
  51. % Ein kleiner Trick zur Darstellung der Determinantenschreibweise, da
  52. % der senkrechte Strich in \.{CWEB} eine besondere Bedeutung besitzt.
  53. %
  54. \def\leftbar{\left|}
  55. \def\rightbar{\right|}
  56.  
  57. % Wir brauchen kein Inhaltsverzeichnis, da nur zwei Kapitel existieren.
  58. %
  59. \nocon
  60.  
  61. @i ecma94.w
  62.  
  63. @* Matrizeninversion. Dieses Programm dient zur Invertierung einer
  64. vorgegebenen $4$-reihigen |Matrix|
  65. $$
  66.   A=\left(
  67.     \matrix{
  68.       a_{11}&\cdots&a_{14}\cr
  69.       \vdots&\ddots&\vdots\cr
  70.       a_{41}&\cdots&a_{44}\cr}
  71.   \right)
  72. $$
  73. mit Einträgen $a_{ij}$ aus dem Körper der komplexen Zahlen~{\ams C}.
  74. Ursprünglich wurde es auf einem {\mc PC} mit dem Borland~\CPLUSPLUS/
  75. Compiler entwickelt.  Ein Vorteil dieses Sprachdialektes ist die
  76. Bereitstellung des Datentypes \glqq komplexe Zahl\grqq.  Nach einem
  77. Zwischenstadium als {\mc ANSI-C}-Programm, das ich mit dem {\mc
  78. SAS/C}-6.3 aus der ursprünglichen Form entwickelte, erfolgt nun die
  79. Rückportierung nach \CPLUSPLUS/ mit der neuen Version~6.50 des {\mc
  80. SAS/C}-Systems.  Der Aufbau des Programmes selbst gliedert sich in
  81. folgende Teile:
  82.  
  83. @c
  84. @<Globale \#|include|s  @>@/
  85. @<Versionsnummer       @>@/
  86. @<Funktionsprototypen  @>@/
  87. @<Funktionen           @>@/
  88. @<Die |main|-Funktion  @>
  89.  
  90. @ Den mathematischen Hintergrund für das angewandte Verfahren liefert
  91. das \glqq Taschenbuch der Mathematik\grqq\ von I.~N.~Bronstein und
  92. K.~A.~Semendjajew (B.~G.~Teubner Verlagsgesellschaft Stuttgart und
  93. Leipzig, 25.~Auf\-lage 1991, {\mc ISBN}~3--8154--2000--8).
  94. Auf Seite~154 wird die Berechnung einer inversen Matrix nach der Formel
  95. $$
  96.   Inverse = Matrix^{-1} = {1\over\det Matrix}\left(\matrix{
  97.     A_{11}&\cdots&A_{1n}\cr
  98.           &\cdots&      \cr
  99.     A_{n1}&\cdots&A_{nn}\cr}\right)^{T}
  100. $$
  101. hergeleitet.  Ausgangspunkt ist eine |Dimension|-reihigen |Matrix|, zu der
  102. in den folgenden Schritten die |Determinante| und die |Adjunkte| berechnet
  103. werden.  Bei der Berechnung der |Inverse|n anhand dieser Formel ist zu
  104. beachten, daß die Transposition der |Adjunkte|n einfach durch
  105. Vertauschung der Zeilen- und Spaltenindizes geschieht.
  106. @^Taschenbuch der Mathematik@>
  107. @^Bronstein, Ilja N.@>
  108. @^Semendjajew, K. A.@>
  109.  
  110. @<Berechne die |Inverse|@>=
  111.    for(i=0; i<Dimension; i++) {
  112.       for(j=0; j<Dimension; j++)
  113.          Inverse[i][j] = Adjunkte[j][i]/Determinante;
  114.       }
  115.  
  116. @ Der aufwendigste Teil dieser Formel steckt in der Berechnung der
  117. |Adjunkte|n zur $4$-reihigen komplexen |Matrix|.  (Die Dimension spielt
  118. mathematisch keine Rolle, programmtechnisch muß aber für andere
  119. |Dimension|en eine Anpassung vorgenommen werden.)  Diese setzt sich zusammen
  120. aus den algebraischen Komplementen~$A_{ij}$ der Elemente~$a_{ij}$ der
  121. |Matrix|, die sich nach der Formel
  122. $$
  123.   A_{ij} = (-1)^{i+j}\leftbar\matrix{
  124.     a_{11}   &\cdots&a_{1,j-1}  &a_{1,j+1}  &\cdots&a_{1n}   \cr
  125.     \ldots   &      &\ldots     &\ldots     &      &\ldots   \cr
  126.     a_{i-1,1}&\cdots&a_{i-1,j-1}&a_{i-1,j+1}&\cdots&a_{i-1,n}\cr
  127.     a_{i+1,1}&\cdots&a_{i+1,j-1}&a_{i+1,j+1}&\cdots&a_{i+1,n}\cr
  128.     \ldots   &      &\ldots     &\ldots     &      &\ldots   \cr
  129.     a_{n1}   &\cdots&a_{n,j-1}  &a_{n,j+1}  &\cdots&a_{nn}  \cr}
  130.   \rightbar
  131. $$
  132. berechnen (Bronstein, Seite~149, |n==Dimension|).  Für die
  133. Implementierung benötigen wir die $3$-reihige |Hilfsmatrix| und die
  134. Variable |Faktor|, die die Potenz von $-1$ repräsentiert.
  135. @^Taschenbuch der Mathematik@>
  136. @^Beschränkung der Allgemeinheit@>
  137.  
  138. @s complex int
  139.  
  140. @<Funktionen@>=
  141. void AdjunkteMatrix(complex **Matrix,complex **Adjunkte)
  142.    {
  143.    int i,j,corralloc = 1;
  144.    complex **Hilfsmatrix,Faktor;
  145.  
  146.    @<Allokiere die |Hilfsmatrix|@>@;
  147.  
  148.    if(corralloc) {
  149.       for(i=0; i<4; i++) {
  150.          @<Setze den Vorfaktor für die adjunkte Determinante@>@;
  151.  
  152.          for(j=0; j<4; j++) {
  153.             @<Streiche Zeile |i| und Spalte |j|               @>@;
  154.             @<Berechne die Determinante der |Hilfsmatrix|     @>@;
  155.             @<Multipliziere die Determinante mit dem Vorfaktor@>@;
  156.  
  157.             Faktor *= complex(-1.); /* |Faktor| wechselt spaltenweise */
  158.             }
  159.          }
  160.       }
  161.  
  162.    @<Gib den Speicher der |Hilfsmatrix| wieder frei@>@;
  163.    }
  164.  
  165. @ Der Vorfaktor in dieser allgemeinen Formel bestimmt sich aus der Potenz
  166. von~$-1$ nach der Summe aus Spaltennummer und Zeilennummer des gerade
  167. betrachteten |Matrix|elementes~$a_{ij}$.  Zu beachten ist dabei, daß in
  168. \CEE/ Vektoren und damit auch Matrizen nicht bei~$1$ sondern bei~$0$ beginnend
  169. indiziert werden.  Da es sich aber um ein zweidimensionales Objekt handelt,
  170. hebt sich die quadratische Potenz von~$-1$ wieder auf.
  171.  
  172. @<Setze den Vorfaktor für die adjunkte Determinante@>=
  173.    for(Faktor=complex(1.),j=0; j<i; j++)
  174.       Faktor *= complex(-1.);
  175.  
  176. @ Die angegebene Determinantendarstellung besagt, daß man die
  177. Ausgangsmatrix um die Zeile~|i| und die Spalte~|j| des gerade betrachteten
  178. Elementes \glqq reduzieren\grqq\ muß, bevor man die Determinante
  179. berechnen darf.  Im Programm wird dazu aus der Ausgangsmatrix die
  180. entsprechend verkleinerte |Hilfsmatrix| gebildet.
  181.  
  182.  @<Streiche Zeile |i| und Spalte |j|@>=
  183.    MatrixReduktion(4,Matrix,Hilfsmatrix,i,j);
  184.  
  185. @ Die Reduktion der |Matrix| zur |Dimension-1|-reihigen |Hilfsmatrix|
  186. geschieht durch Streichen der Zeile~|i| und der Spalte~|j|.  Da dieser
  187. Vorgang für jedes der |Dimension|$^2$ Elemente der |Matrix|
  188. durchgeführt werden muß, wird dazu eine elementare Funktion
  189. definiert, die sogar mit einer anderen |Dimension| als~$4$ eingesetzt
  190. werden kann.  Die Zählvariablen |k| und~|l| bezeichnen die
  191. Zeilen beziehungsweise die Spalten der Ausgangs-|Matrix|, |m|~und~|n|
  192. die der |Hilfsmatrix|.
  193.  
  194. @<Funktionen@>=
  195. void MatrixReduktion(int Dimension,complex **Matrix,@|
  196. complex **Hilfsmatrix,int i,int j)
  197.    {
  198.    int k,l,m,n;
  199.  
  200.    for(k=0,m=0; k<Dimension; k++) {
  201.       if(k!=i) { /* Zeile wird ausgelassen für |k==i| */
  202.          for(l=0,n=0; l<Dimension; l++) {
  203.             if(l!=j) { /* Spalte wird ausgelassen für |l==j| */
  204.                Hilfsmatrix[m][n] = Matrix[k][l];
  205.                n++; /* Nächste Spalte der |Hilfsmatrix| */
  206.                }
  207.             }
  208.          m++; /* Nächste Zeile der |Hilfsmatrix| */
  209.          }
  210.       }
  211.    }
  212.  
  213. @ Als Zwischenschritt folgt nun die Berechnung der Determinante der
  214. |Hilfsmatrix|.  Diese wird bereits in das entsprechende Feld der
  215. |Adjunkte|n gestellt, das aber noch mit dem getrennt berechneten Faktor
  216. multipliziert werden muß.
  217.  
  218. @<Berechne die Determinante der |Hilfsmatrix|@>=
  219.    Adjunkte[i][j] = ComplexDet(Hilfsmatrix);
  220.  
  221. @ Im vorliegenden Programm zur Berechnung einer |Inverse|n der
  222. |Dimension|~$4$ haben wir es stets mit einer $3$-dimensionalen
  223. |Hilfsmatrix| zu tun.  Deren Determinante (beachte die Schreibweise) wird
  224. nach der Beispielformel~2 von Seite~149 aus Bronstein berechnet (Regel von
  225. Sarrus)
  226. $$
  227.   \leftbar\matrix{
  228.     a_{11}&a_{12}&a_{13}\cr
  229.     a_{21}&a_{22}&a_{23}\cr
  230.     a_{31}&a_{32}&a_{33}\cr}\rightbar=
  231.   (a_{11}a_{22}a_{33} + a_{12}a_{23}a_{31} + a_{13}a_{21}a_{32})-
  232.   (a_{13}a_{22}a_{31} + a_{11}a_{23}a_{32} + a_{12}a_{21}a_{33}).
  233. $$
  234. @^Taschenbuch der Mathematik@>
  235. @^Beschränkung der Allgemeinheit@>
  236.  
  237. @d ComplexDet(H) @/
  238.   (H[0][0]*H[1][1]*H[2][2]+H[0][1]*H[1][2]*H[2][0]+H[0][2]*H[1][0]*H[2][1])-@/
  239.   (H[0][2]*H[1][1]*H[2][0]+H[0][0]*H[1][2]*H[2][1]+H[0][1]*H[1][0]*H[2][2])
  240.  
  241. @ Der berechnete Zwischenwert muß noch mit dem vorher definierten 
  242. |Faktor| multipliziert werden, damit das endgültige algebraische
  243. Komplement~$A_{ij}$ entsteht.
  244.  
  245. @<Multipliziere die Determinante mit dem Vorfaktor@>=
  246.    Adjunkte[i][j] *= Faktor;
  247.  
  248. @ Nach der Aufstellung der |Adjunkte|n zur |Matrix| benötigen wir jetzt
  249. noch die |Determinante|.  Erfreulicherweise ist dazu nun kein großer
  250. Aufwand mehr nötig, da diese nach dem Laplaceschen Entwicklungssatz
  251. $$
  252.   Determinante=\sum_{i=1}^{n}a_{ij}A_{ij}=\sum_{j=1}^{n}a_{ij}A_{ij}
  253. $$
  254. aus den Elementen der |Matrix| und der zugehörigen |Adjunkte|n berechnet
  255. werden kann (Bronstein, Seite~150).  Dabei ist es egal, nach welcher Zeile
  256. oder Spalte die Entwicklung durchgeführt wird.  Wir verwenden die erste
  257. Spalte.
  258. @^Taschenbuch der Mathematik@>
  259.  
  260. @<Laplace-Entwicklung der |Determinante|n@>=
  261.    Determinante = complex(0.);
  262.    for(i=0; i<Dimension; i++)
  263.       Determinante += Matrix[i][0]*Adjunkte[i][0];
  264.  
  265. @ Nach der Darlegung des mathematischen Formelwerkes und dessen Umsetzung
  266. in \CEE/-Routinen folgt nun das Hauptprogramm, das den Rahmen für die
  267. Anwendung der beschriebenen Funktionen bildet.  Zusätzlich verwendet es
  268. weitere Unterroutinen, die rein programmiertechnischer Natur sind und
  269. im folgenden unabhängig vom mathematischen Problem beschrieben werden.
  270.  
  271. @<Die |main|-Funktion@>=
  272. int main()
  273.    {
  274.    complex **Matrix,**Adjunkte,**Inverse;
  275.    complex Determinante;
  276.    int i,j,Dimension=4,corralloc=1;
  277.  
  278.    @<Allokiere die zu invertierende |Matrix|@>@;
  279.    @<Allokiere die |Adjunkte|               @>@;
  280.    @<Allokiere die |Inverse|                @>@;
  281.  
  282.    if(corralloc) {
  283.       MatrixInit(Dimension,Matrix);
  284.       MatrixDisplay(Dimension,Matrix);
  285.       AdjunkteMatrix(Matrix,Adjunkte);
  286.       @<Laplace-Entwicklung der |Determinante|n@>@;
  287.       @<Berechne die |Inverse|                 @>@;
  288.       MatrixDisplay(Dimension,Inverse);
  289.       }
  290.  
  291.    @<Gib den Speicher wieder frei@>@;
  292.    return(corralloc);
  293.    }
  294.  
  295. @ Für die formatierte Ein- und Ausgabe, die dynamische Speicherverwaltung
  296. sowie die mathematischen Funktionen benötigen wir die
  297. Standarddeklarationen, wie sie in den Include-Dateien zu finden sind.
  298.  
  299. @<Globale \#|include|s@>=
  300. #include <math.h>
  301. #include <complex.h>
  302. #include <stdio.h>
  303. #include <stdlib.h>
  304. @<Zusätzliche Deklarationen für den Coprozessor@>
  305.  
  306. @ Bei der Benutzung des mathematischen Coprozessors sollten zusätzlich zu
  307. {\tt math.h} die speziellen Funktionsdeklarationen eingebunden werden.
  308. Dies gilt in diesem Fall speziell für den Commodore Amiga und den {\mc
  309. ANSI-C}-Compiler von {\mc SAS}~Institute, Cary (North Carolina).
  310.  
  311. @<Zusätzliche Deklarationen für den Coprozessor@>=
  312. #ifdef _M68881
  313. #include <m68881.h>
  314. #endif
  315. @^Systemabhängigkeiten@>
  316.  
  317. @ Die aktuelle Versionsnummer dieses Programmes wird nach dem \glqq Style
  318. Guide\grqq\ von Commodore in einer globalen Formatzeichenkette abgelegt und
  319. kann mit der Systemroutine {\tt version Matrix} abgefragt werden.
  320.  
  321. @<Versionsnummer@>=
  322. const char *Version = "$VER: MATRIXINVERTIERUNG 2.0 (20.11.1993)";
  323. @^Systemabhängigkeiten@>
  324.  
  325. @ Die meisten Routinen dieses Programmes sind unabhängig von der
  326. gewählten |Dimension| des Problems.  Alle aber stellen nur minimale
  327. Forderungen an die Gestalt der verwendeten Matrizen, da sie lediglich mit
  328. Zeigern auf entsprechende Felder versorgt werden müssen.  Damit
  329. läßt sich aber auch die Eingabe des Ausgangsproblems fast beliebig
  330. gestalten.  Bei dieser allgemeinen Implementierung kann dies auf zwei
  331. verschiedene Weisen geschehen.  Standardeingabe ist die Datei
  332. \glq{\tt Matrix.input}\grq, falls diese im aktuellen Verzeichnis vorhanden
  333. ist.  Falls nicht, wird der Benutzer zur elementweisen Eingabe der
  334. komplexen Elemente der |Matrix| aufgefordert.  Wird eine andere
  335. Verfahrensweise gewünscht, so muß lediglich diese Funktion zur Eingabe
  336. und die weiter unten beschriebene Funktion zur Ausgabe der Problemstellung
  337. geändert oder angepaßt werden.
  338.  
  339. @<Funktionen@>=
  340. void MatrixInit(int Dimension,complex **Matrix)
  341.    {
  342.    int i,j;
  343.    double Realteil,Imagteil;
  344.    FILE *fp;
  345.  
  346.    if(fp = fopen("Matrix.input","r")) {
  347.       for(i=0; i<Dimension; i++) {
  348.          for(j=0; j<Dimension; j++) {
  349.             fscanf(fp,"(%lf,%lf)",&Realteil,&Imagteil);
  350.             Matrix[i][j] = complex(Realteil,Imagteil);
  351.             }
  352.          }
  353.       fclose(fp);
  354.       }
  355.    else {
  356.       for(i=0; i<Dimension; i++) {
  357.          for(j=0; j<Dimension; j++) {
  358.             printf("Real A[%d][%d] = ",i+1,j+1);
  359.             scanf("%lf",&Realteil);
  360.             printf("Imag A[%d][%d] = ",i+1,j+1);
  361.             scanf("%lf",&Imagteil);
  362.             Matrix[i][j] = complex(Realteil,Imagteil);
  363.             }
  364.          fputc('\n',stdout);
  365.          }
  366.       }
  367.    }
  368. @^Beschränkung der Allgemeinheit@>
  369. @^Systemabhängigkeiten@>
  370.  
  371. @ Ebenso einfach wie die Eingabe ist auch die Ausgaberoutine gestaltet.
  372. Sie zeigt eine quadratische |Dimension|-reihige |Matrix| mit komplexen
  373. Einträgen zum einen am Bildschirm an und schreibt gleichzeitig das
  374. Ergebnis im gleichen Format in die Datei \glq{\tt Matrix.output}\grq, das
  375. beim Einlesen aus \glq{\tt Matrix.input}\grq\ erwartet wird.
  376.  
  377. @<Funktionen@>=
  378. void MatrixDisplay(int Dimension,complex **Matrix)
  379.    {
  380.    int i,j;
  381.    FILE *fp;
  382.  
  383.    fp = fopen("Matrix.output","w");
  384.    for(i=0; i<Dimension; i++) {
  385.       for(j=0; j<Dimension; j++) {
  386.          if(fp) fprintf(fp,"(%lf,%lf)",real(Matrix[i][j]),imag(Matrix[i][j]));
  387.          printf("(%lf,%lf) ",real(Matrix[i][j]),imag(Matrix[i][j]));
  388.          }
  389.       if(fp) fputc('\n',fp);
  390.       fputc('\n',stdout);
  391.       }
  392.    fputc('\n',stdout);
  393.    fclose(fp);
  394.    }
  395. @^Beschränkung der Allgemeinheit@>
  396. @^Systemabhängigkeiten@>
  397.  
  398. @ Was ein echtes \CEE/-Programm sein will, das verwendet so wenig wie
  399. möglich feste Größen bei der Definition von Speicherflächen.
  400. Zwar sind in diesem Fall alle Dimensionen bekannt und bei jedem Lauf immer
  401. gleich, aber trotzdem ist es eine nette Übung, den benötigten
  402. Speicherplatz \glqq dynamisch\grqq\ anzufordern und nach seiner Benutzung
  403. wieder ordnungsgemäß freizugeben.  Die |Matrix|, ihre |Adjunkte| und
  404. die zu berechnende |Inverse| werden lokal in |main| als Zeigervariablen
  405. definiert und erhalten auch lokal ihren Speicherplatz zugewiesen.
  406.  
  407. @<Allokiere die zu invertierende |Matrix|@>=
  408.    if(Matrix = (complex **)calloc(Dimension,sizeof(complex *))) {
  409.       for(i=0; i<Dimension; i++)
  410.          if(!(Matrix[i] = (complex *)calloc(Dimension,sizeof(complex))))
  411.             corralloc = 0;
  412.       }
  413.    else corralloc = 0;
  414.  
  415. @ @<Allokiere die |Adjunkte|@>=
  416.    if(Adjunkte = (complex **)calloc(Dimension,sizeof(complex *))) {
  417.       for(i=0; i<Dimension; i++)
  418.          if(!(Adjunkte[i] = (complex *)calloc(Dimension,sizeof(complex))))
  419.             corralloc = 0;
  420.       }
  421.    else corralloc = 0;
  422.  
  423. @ @<Allokiere die |Inverse|@>=
  424.    if(Inverse = (complex **)calloc(Dimension,sizeof(complex *))) {
  425.       for(i=0; i<Dimension; i++)
  426.          if(!(Inverse[i] = (complex *)calloc(Dimension,sizeof(complex))))
  427.             corralloc = 0;
  428.       }
  429.    else corralloc = 0;
  430.  
  431. @ Nach der erfolgreichen Durchführung aller Berechnungsschritte muß vor
  432. Beendigung des Programmes der angeforderte Speicher wieder freigegeben werden.
  433. Dies geschieht in umgekehrter Reihenfolge zur Allokierung.
  434.  
  435. @d FreeObject(A) if(A) free(A);
  436.  
  437. @<Gib den Speicher wieder frei@>=
  438.    for(i=Dimension-1; i>=0; i--) {
  439.       FreeObject(Inverse[i]);
  440.       FreeObject(Adjunkte[i]);
  441.       FreeObject(Matrix[i]);
  442.       }
  443.  
  444.    FreeObject(Inverse);
  445.    FreeObject(Adjunkte);
  446.    FreeObject(Matrix);
  447.  
  448. @ Noch radikaler als bei den genannten Matrizen erfolgt die Lokalisierung
  449. der |Hilfsmatrix|.  Sie wird erst innerhalb der Funktion |AdjunkteMatrix|
  450. definiert und mit Speicherplatz besorgt.
  451.  
  452. @<Allokiere die |Hilfsmatrix|@>=
  453.    if(Hilfsmatrix = (complex **)calloc(3,sizeof(complex *))) {
  454.       for(i=0; i<3; i++)
  455.          if(!(Hilfsmatrix[i] = (complex *)calloc(3,sizeof(complex))))
  456.             corralloc = 0;
  457.       }
  458.    else corralloc = 0;
  459. @^Beschränkung der Allgemeinheit@>
  460.  
  461. @ @<Gib den Speicher der |Hilfsmatrix| wieder frei@>=
  462.    for(i=0; i<3; i++) FreeObject(Hilfsmatrix[i]);
  463.    FreeObject(Hilfsmatrix);
  464. @^Beschränkung der Allgemeinheit@>
  465.  
  466. @ Als letztes Modul im Programmfluß angelegt, jedoch in der
  467. endgültigen \CEE/-Quelldatei sehr weit vorne, stehen hier die Prototypen
  468. aller verwendeten Funktionen.  Die Beschreibung der Parameterliste und die
  469. Angabe des Rückgabewertes ermöglicht es dem Compiler, eventuelle
  470. Programmierfehler festzustellen und zu melden.
  471.  
  472. @<Funktionsprototypen@>=
  473. void MatrixInit(int,complex **);                        @/
  474. void MatrixReduktion(int,complex **,complex **,int,int);@/
  475. void MatrixDisplay(int,complex **);                     @/
  476. void AdjunkteMatrix(complex **,complex **);             @/
  477. int main(void);
  478.  
  479. @* Index.  Zum Abschluß der Dokumentation folgen noch das
  480. Stichwortverzeichnis mit sämtlichen verwendeten Bezeichnern sowie eine
  481. Zusammenfassung aller Programmodule.  Zu beachten sind insbesondere die
  482. Einträge \glqq Beschränkung der Allgemeinheit\grqq\ und \glqq
  483. Systemabhängigkeiten\grqq.
  484.